﻿var gameDao = require("./../dao/gameDao");
var gameConfig = require("./../config/gameConfig");
var redis_laba_win_pool = require("./../../util/redis_laba_win_pool");
var configDao = require("./../dao/configDao");
var log = require("./../../util/loginfo").getInstand;

arithmetic = function (_idx) {
    //相关属性
    //调试是否显示相关数据
    var debug = false;

    //算法说明：
    //游戏倍数分别为
    //2,5,20,3,10,40,5,15,60,7,20,100,30,200,100,10,30,160,15,40,200,20,80,400,50,200,100
    //所以以上的概率为50%,20%,5%
    //
    //
    //本算法说明，先选中组合，然后再尝试他的概率。
    var bet = [[2, 5, 20], [5, 15, 60], [10, 30, 160], [20, 80, 400], [50, 200, 1000], [100, 400, 2000], [0, 0, 0]];
    var linesPoint = [[5, 6, 7, 8, 9], [0, 1, 2, 3, 4], [10, 11, 12, 13, 14], [0, 6, 12, 8, 4], [10, 6, 2, 8, 14], [0, 1, 7, 3, 4], [10, 11, 7, 13, 14], [5, 11, 12, 13, 9], [5, 1, 2, 3, 9]]
    //所有击中的bet
    var pro = [2, 5, 10, 15, 20, 30, 60, 50, 80, 100, 160, 200, 400, 1000, 2000];
    //var pro_p = [50,50,50,50,50,50,50,50,50,50,50,40,30,20,10];
    var pro_p = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5];
    //免费次数
    var freeCountArr = [10, 20, 30];
    //可选择倍数
    var betCountObj = {};
    betCountObj[1] = 1;
    betCountObj[2] = 2;
    betCountObj[5] = 3;
    betCountObj[10] = 4;
    betCountObj[20] = 5;
    betCountObj[50] = 6;
    betCountObj[100] = 7;
    var betCount = [1, 10, 20, 50, 100];


    //pro 能整除最大值
    this.pro_max = new Array();
    //pro 个数
    this.pro_max_count = new Array();
    //外部控制倍率
    this.controlBet = 0.98;
    //超级大奖占成
    this.poolBet = 0.01;
    //最大公约数
    this.max_pro = 0;

    this._testMax = 0;

    //分数数组
    this.scoreArr = {};

    //虚拟奖池
    this.virtual_score_pool = 1000000;
    //实际奖池
    this.score_pool = [];

    //========================================
    //水位
    this.nGamblingWaterLevelGold = 0;
    //库存
    this.nGamblingBalanceGold = 0;
    //奖池
    this.nGamblingWinPool = 0;
    //大奖幸运等级
    this.nGamblingBigWinLevel = [];
    //大奖幸运概率
    this.nGamblingBigWinLuck = [];

    this.printPool = function () {
        for (var i = 0; i < betCount.length; ++i) {
            log.info("i:" + i + "-" + this.score_pool[i]);
        }
    }

    //获得实际奖池
    this.getScorePool = function (_betIdx) {
        if (this.score_pool[_betIdx]) {
            this.printPool();
            return this.score_pool[_betIdx];
        } else {
            //this.printPool();
            return 0
        }

    }

    this.getScorePoolList = function () {
        return this.score_pool;
    }

    this.getScorePoolListLength = function () {
        return betCount.length;
    }

    this.getScoreId = function () {
        return betCount;
    }


    this.getGamblingBalanceGold = function () {
        //获取库存 奖池   数据库同步使用
        var dict = {
            nGamblingBalanceGold: this.nGamblingBalanceGold,
            nGamblingWinPool: this.nGamblingWinPool
        };

        return dict

    }
    this.addGamblingBalanceGold = function (Gold, Pool) {
        //添加库存 奖池   数据库同步使用
        this.nGamblingBalanceGold += parseInt(Gold);
        this.nGamblingWinPool += parseInt(Pool);
        log.info("添加库存:" + Gold);
        log.info("添加奖池:" + Pool);
        log.info(this.nGamblingBalanceGold);
        log.info(this.nGamblingWinPool)
        //redis存储奖池
        redis_laba_win_pool.redis_win_pool_incrby(parseInt(Pool))
    }
    this.subGamblingBalanceGold = function (Gold, Pool) {
        //减少库存   奖池 数据库同步使用
        //this.nGamblingBalanceGold-= parseInt(Gold);
        this.nGamblingWinPool -= parseInt(Pool);
        log.info("减少库存:" + Gold);
        log.info("减少奖池:" + Pool);
        log.info(this.nGamblingBalanceGold);
        log.info(this.nGamblingWinPool);

        //redis奖池
        redis_laba_win_pool.redis_win_pool_decrby(parseInt(Pool))
    }
    this.getGamblingBalanceLevelBigWin = function () {
        //获取库存  水位 奖池 幸运值   判断中奖使用
        var value = {
            nGamblingWaterLevelGold: this.nGamblingWaterLevelGold,
            nGamblingBalanceGold: this.nGamblingBalanceGold,
            nGamblingWinPool: this.nGamblingWinPool,
            nGamblingBigWinLevel: this.nGamblingBigWinLevel,
            nGamblingBigWinLuck: this.nGamblingBigWinLuck
        }
        return value;
    }

    //添加实际奖池
    this.addScorePool = function (_betIdx, _socre) {
        if (this.score_pool[_betIdx]) {
            this.score_pool[_betIdx] += parseInt(_socre);
        } else {
            this.score_pool[_betIdx] = 0;
            this.score_pool[_betIdx] += parseInt(_socre);
        }

        this.printPool();
    }

    //减少奖池
    this.subScorePool = function (_betIdx) {
        if (this.score_pool[_betIdx]) {
            this.score_pool[_betIdx] -= this.subValue;
        } else {
            this.score_pool[_betIdx] = 0;
        }
        this.printPool();
    }

    this.getAllcaishenValue = function () {
        //获得全财神的值
        return this.subValue;
    }

    //获得奖池
    this.getVirtualScorePool = function () {
        //var result = {virtual_score_pool:this.virtual_score_pool,score_pool}
        return this.virtual_score_pool;
    }

    //添加奖池
    this.addVirtualScorePool = function (score_bet) {
        this.virtual_score_pool += parseInt(score_bet);
    }

    //减少虚拟奖池
    this.subVirtualScorePool = function (score_bet, flag) {
        this.subValue = Math.floor((this.virtual_score_pool / 100 * score_bet * 0.9));
        if (flag) {
            this.virtual_score_pool -= this.subValue;
        } else {
            if (this.virtual_score_pool - this.subValue > 900000 || this.virtual_score_pool > 2000000) {
                this.virtual_score_pool -= this.subValue;
            }
        }

    }

    this.init = function () {
        //初始化水位和库存
        this.initGamblingGame();
    }

    this.initHitPro = function () {
        this.hitpro = [];
        this.hitproMax = 0;
        for (var i = 0; i < pro_p.length; ++i) {

            for (var j = 0; j < pro_p[i]; ++j) {
                this.hitpro[this.hitproMax + j] = i;
            }
            this.hitproMax += pro_p[i];
        }

    }

    this.initBetArr = function () {
        this.proCount = new Array();
        this.HitTimes = new Array();
        for (var i = 0; i < pro.length; ++i) {
            this.proCount[i] = new Array();
            this.HitTimes[i] = new Array();
            this.pro_max_count[i] = Math.floor(10000 / pro[i]);
            this.pro_max[i] = this.pro_max_count[i] * pro[i];
            this.pro_max_count[i] = Math.floor(this.pro_max_count[i] * (this.controlBet - this.poolBet));
            for (var j = 0; j < betCount.length; j++) {
                //开始创建10000数组
                this.proCount[i][j] = new Array();
                this.HitTimes[i][j] = 0;
                for (var k = 0; k < 9999; ++k) {
                    //先把所有先定制为0;
                    this.proCount[i][j][k] = 0;
                }
                var point = 0;

                for (var k = 0; k < this.pro_max_count[i]; ++k) {
                    //插入数据
                    point += Math.floor(Math.random() * pro[i]);
                    this.proCount[i][j][point] = 1;
                    ++point;
                }
                //随机打乱
                for (var z = 0; z < 10; z++) {
                    for (var k = 0; k < 5000; ++k) {
                        var temp = this.proCount[i][j][k];
                        var idx = Math.floor(Math.random() * this.pro_max[i]);
                        this.proCount[i][j][k] = this.proCount[i][j][idx];
                        this.proCount[i][j][idx] = temp;
                    }
                }
            }
        }
    };

    this.initArrData = function () {
        //test
        this.createArr(100000);
        log.info("生成分数数据");
    };

    this.initPool = function () {
        var self = this;

        gameDao.getScore_pools(function (Result) {

            for (var i = 0; i < Result.length; ++i) {
                if (Result[i].id == 0) {
                    self.virtual_score_pool = Result[i].score_pool;
                } else {
                    for (var j = 0; j < betCount.length; ++j) {
                        if (betCount[j] == Result[i].id) {
                            self.score_pool[j] = Result[i].score_pool;
                            break;
                        }
                    }
                }
            }

            log.info("读取采池数据完毕!")
        })


    }


    //获得当前概率
    this.getBet = function () {
        return this.controlBet;
    }

    //设置概率
    this.setBet = function (_bet) {
        this.controlBet = _bet;
    }



    this.CheckBet = function (_betIdx) {
        return betCount[_betIdx];
    }

    this.Check_bet_dict = function (bet_dict) {
        //检查下注字典
        if ([0,1,2].indexOf(bet_dict.bet_res)==-1) {
            log.info("缺少字段bet_res");
            return false;
        }
        if (bet_dict.bet_gold == undefined || bet_dict.bet_gold == null || bet_dict.bet_gold == 0) {
            log.info("缺少字段bet_gold");
            return false;
        }
        return true
    };


    //var hitCount_t = 0;
    //用户获得数组
    this.getArray = function (_betIdx, _LotteryCount) {

        var betValue = betCount[_betIdx];

        //获取倍数,_bet是倍数的ID
        if (!betValue) {
            log.info(_betIdx + "没有这个概率");
            var ServerArray = [[1, 2, 3, 4, 6],
                [1, 2, 3, 4, 6],
                [1, 2, 3, 4, 6]];
            return ServerArray;
        }

        //获得前,先更新一下数组
        this.createArr(1);

        //产生随机数删掉虚拟池
        var rand = Math.floor(Math.random() * 10000);

        if (rand == 0 && _LotteryCount > 5000) {

            //检测实际实际奖池是否能发
            if (this.getScorePool(_betIdx) > 10000 * betValue) {
                //发奖励
                log.info("发大奖!");
                log.info("_LotteryCount:" + _LotteryCount);
                this.subVirtualScorePool(betValue, true);
                this.subScorePool(_betIdx);

                var ServerArray = [[6, 6, 6, 6, 6],
                    [6, 6, 6, 6, 6],
                    [6, 6, 6, 6, 6]];

                return ServerArray;
            } else {
                this.subVirtualScorePool(betValue, false);
            }
        }


        //尝试击中
        var total_temp = 0;
        for (var i = 0; i < 10; ++i) {
            var now_pro_p = Math.floor(Math.random() * this.hitproMax);

            var now_pro = this.hitpro[now_pro_p];
            //now_pro 是鱼的IDX, betidx 是倍率IDX
            //now_pro-为正常
            //0-调试 只中2分
            //now_pro = 0;
            if (this.hit(now_pro, _betIdx, 10)) {
                total_temp += pro[now_pro];
            }
        }


        //原计划是
        sourcetotal_temp = total_temp;
        //寻找相近的数组
        while (!(this.scoreArr[total_temp])) {
            --total_temp;
        }

        var idx = Math.floor(Math.random() * this.scoreArr[total_temp].length);

        //加入虚拟彩池
        if (total_temp == 0) {
            var virtual_score_pool_before = this.getVirtualScorePool();
            this.addVirtualScorePool(betValue);
            var virtual_score_pool_current = this.getVirtualScorePool();
            //入库
            //var userInfo = {userid:_userId,score_pool_before:score_pool_before,score_pool_value:betValue,
            //	score_pool_current:score_pool_current,virtual_score_pool_before:virtual_score_pool_before,
            // 	virtual_score_pool_value:betValue,virtual_score_pool_current:virtual_score_pool_current}
            //gameDao.score_poolLog(userInfo);

        } else {
            if (debug) {
                log.info(this.scoreArr[total_temp][idx])
            }
        }

        //增加免费次数
        if (total_temp >= 10) {
            var i = 100;
            var tempitem = this.check(this.scoreArr[total_temp][idx]);
            while (tempitem.freeCount + tempitem.scoreCount != total_temp && i > 0) {
                idx = Math.floor(Math.random() * this.scoreArr[total_temp].length);
                i--;
            }
        }

        return this.scoreArr[total_temp][idx];
    }

    this.createArr = function (_count) {
        //生成_count个
        for (var times = 0; times < _count; times++) {
            var ResultArray = new Array();
            for (var i = 0; i < 3; i++) {
                ResultArray[i] = new Array();
                for (var j = 0; j < 5; j++) {
                    ResultArray[i][j] = Math.floor(Math.random() * bet.length)
                }
            }
            //获得分数

            var info = this.check(ResultArray, 0);


            if (this.scoreArr[(info.scoreCount + info.freeCount)]) {
                //分数已经存在
                if (this.scoreArr[(info.scoreCount + info.freeCount)].length < 500) {
                    //只存500组
                    this.scoreArr[(info.scoreCount + info.freeCount)].push(ResultArray);
                } else {
                    this.scoreArr[(info.scoreCount + info.freeCount)].shift()
                    this.scoreArr[(info.scoreCount + info.freeCount)].push(ResultArray);
                }
            } else {
                //分数还未存在
                this.scoreArr[(info.scoreCount + info.freeCount)] = new Array();
                this.scoreArr[(info.scoreCount + info.freeCount)].push(ResultArray);
            }
        }
    }

    //1.0 正式版本,免费次数版本
    this.check = function (reArray, _debug) {
        //检查分数总和
        var scoreCount = 0;

        var freeCount = 0;

        //判断是否是全屏元宝
        var max_yuanbao = true;
        for (var i = 0; i < reArray.length && max_yuanbao; i++) {
            for (var j = 0; j < reArray[0].length; j++) {
                if (reArray[i][j] != 5) {
                    max_yuanbao = false;
                    break;
                }
            }
        }

        if (max_yuanbao) {
            log.info("全百变");
            return 0;
        }
        //判断全屏财神
        var max_caisheng = true;
        for (var i = 0; i < reArray.length && max_caisheng; i++) {
            for (var j = 0; j < reArray[0].length; j++) {
                if (reArray[i][j] != 6) {
                    max_caisheng = false;
                    break;
                }
            }
        }

        if (max_caisheng) {
            log.info("全免费");
            log.info("中奖:" + this.subValue)
            return {scoreCount: this.subValue, freeCount: 0, bigScore: 1};
        }

        for (var i = 0; i < 9; i++) {

            //从左到右
            var j = 0;
            var sameCard = -1;
            var sameCardCount = 1;
            sameCardCount = 1;
            for (j = 0; j < linesPoint[0].length; ++j) {
                //获得坐标

                var row = Math.floor(linesPoint[i][j] / 5);
                var col = linesPoint[i][j] % 5;

                if (sameCard == -1) {
                    //得到第一个
                    if (reArray[row][col] == -1) break;
                    sameCard = reArray[row][col];
                    continue;
                }

                if (reArray[row][col] == sameCard || (sameCard != 6 && reArray[row][col] == 5)) {
                    ++sameCardCount;

                } else {
                    //不能再找到相同的
                    if (sameCard == 5 && reArray[row][col] != -1 && reArray[row][col] != 6) {
                        sameCard = reArray[row][col];
                        ++sameCardCount;
                    } else {
                        break;
                    }
                }

            }
            //得出结果
            if (sameCardCount > 2) {
                if (debug && _debug) {
                    log.info("left===line:" + (i + 1) + " sameCard:" + sameCard + " sameCardCount:" + sameCardCount + " score:" + bet[sameCard][sameCardCount - 3]);
                }
                scoreCount += bet[sameCard][sameCardCount - 3]
                //如果是财神,统计

                if (sameCard == 6) {
                    freeCount += freeCountArr[sameCardCount - 3];
                }

            }

            //从右到左
            if (sameCardCount != 5) {
                sameCard = -1;
                sameCardCount = 1;
                sameCardCount = 1;
                for (j = linesPoint[0].length - 1; j >= 0; --j) {
                    //获得坐标

                    var row = Math.floor(linesPoint[i][j] / 5);
                    var col = linesPoint[i][j] % 5;

                    if (sameCard == -1) {
                        //得到第一个
                        if (reArray[row][col] == -1) break;
                        sameCard = reArray[row][col];
                        continue;
                    }

                    if (reArray[row][col] == sameCard || (sameCard != 6 && reArray[row][col] == 5)) {
                        ++sameCardCount;

                    } else {
                        //不能再找到相同的
                        if (sameCard == 5 && reArray[row][col] != -1 && reArray[row][col] != 6) {
                            sameCard = reArray[row][col];
                            ++sameCardCount;
                        } else {
                            break;
                        }
                    }
                }
                //得出结果
                if (sameCardCount > 2) {
                    if (debug && _debug)
                        log.info("right===line:" + (i + 1) + " sameCard:" + sameCard + " sameCardCount:" + sameCardCount + " score:" + bet[sameCard][sameCardCount - 3]);
                    scoreCount += bet[sameCard][sameCardCount - 3]

                    if (sameCard == 6) {
                        freeCount += freeCountArr[sameCardCount - 3];
                        //log.info(freeCount)
                        //freeBet = freeBetArr[sameCardCount - 3];
                    }
                }
            }
        }

        return {scoreCount: scoreCount, freeCount: freeCount, bigScore: 0};
    }

    //=================================================================================================
    this.initGamblingGame = function () {
        var self = this;
        gameDao.getGamblingGame(function (Result) {

            self.nGamblingWaterLevelGold = Result[0].nGamblingWaterLevelGold;  //水位
            self.nGamblingBalanceGold = Result[0].nGamblingBalanceGold;      //库存
            self.nGamblingWinPool = Result[0].nGamblingWinPool;      //奖池

            self.nGamblingBigWinLevel = Result[0].nGamblingBigWinLevel.split(',').map(Number);  //大奖幸运等级
            self.nGamblingBigWinLuck = Result[0].nGamblingBigWinLuck.split(',').map(Number);    //大奖幸运概率

            // //redis存储奖池
            // redis_laba_win_pool.redis_win_pool_incrby(self.nGamblingWinPool)


            log.info("读取采池数据完毕!");
            log.info("水位:" + self.nGamblingWaterLevelGold);
            log.info("库存:" + self.nGamblingBalanceGold);
            log.info("奖池:" + self.nGamblingWinPool);
            // log.info("大奖幸运等级:" + self.nGamblingBigWinLevel);
            // log.info("大奖幸运概率:" + self.nGamblingBigWinLuck);
        })


    }
    this.gameProcessor = function (betInfo_list,nGamblingWaterLevelGold, RewardLongHuNo, isCtrlRoundNO, roundNO) {
        //初始化牌型
        log.info("bet list = " + betInfo_list);
        log.info("water value = " + nGamblingWaterLevelGold);
        var nHideCards = [];
        var POKER=JSON.parse(JSON.stringify(gameConfig.POKER))
        // # 初始化 洗牌
        for(var p in POKER){
            if(POKER[p] != 0x0E01 && POKER[p] != 0x0E02){
                nHideCards.push(POKER[p])
            }
        }
        while (true){
            var long_card = RandomNumForList(nHideCards)
            var hu_card = RandomNumForList(nHideCards)
            if(long_card!=hu_card){
                break
            }
        }

        var long_num = getNumber(long_card);
        var hu_num = getNumber(hu_card);

        var GAME_LONG_HU_DOU_ODDS = gameConfig.GAME_LONG_HU_DOU_ODDS;
        //bet_type  下注类型
        //bet_res   下注结果
        //bet_gold   下注金额
        //# 下注赔率 0龙 1虎 2和
        var is_true_he=false  //判断和是不是有人下注
        for (var i in betInfo_list) {
            var betInfo = betInfo_list[i];    //下注详情
            var res=parseInt(betInfo.bet_res);
            if(res==2){
                is_true_he=true;
                break
            }
        }
        //判断结果
        var win;
        if(long_num==hu_num){    //和
            win=2;
        }else if(long_num>hu_num){  //龙
            win=0;
        }else {                  //虎
            win=1;
        }

        //是否触发风控
        let isNeedChange = false;
        if (RewardLongHuNo >=0 && RewardLongHuNo <=2 && isCtrlRoundNO) {
            if (win != RewardLongHuNo) {
                isNeedChange = true;
                win = RewardLongHuNo;
            }
            configDao.clearLongHuNo(roundNO, function(state) {
                if (state) {
                    log.info("clear longhu config success! round no " + roundNO);
                }
            });
        }
        log.info("RewardLongHuNo " + RewardLongHuNo + " win " + win + " isNeedChange " + isNeedChange);
        while (isNeedChange){
            if (RewardLongHuNo == 0) { //龙
                hu_card = RandomNumForList(nHideCards);
                hu_num = getNumber(hu_card);
                if (long_num == 1) {
                    long_card = RandomNumForList(nHideCards);
                    long_num = getNumber(long_card);
                }
                if ((long_card != hu_card) && (long_num > hu_num)) {
                    break;
                }
            } else if (RewardLongHuNo == 1) { //虎
                long_card = RandomNumForList(nHideCards);
                long_num = getNumber(long_card);
                if (hu_num == 1) {
                    hu_card = RandomNumForList(nHideCards);
                    hu_num = getNumber(hu_card);
                }
                if((long_card != hu_card) && (hu_num > long_num)) {
                    break;
                }
            } else if (RewardLongHuNo == 2) { //和
                hu_card = RandomNumForList(nHideCards);
                hu_num = getNumber(hu_card);
                if((long_card != hu_card) && (long_num == hu_num)) {
                    break;
                }
            }
        }
        log.info("win = "+ win+ " long_card "+ long_card+ " long_num "+ long_num+ " hu_card "+ hu_card+ " hu_num "+ hu_num);

        //算账
        var user_win_list={}     //用户赢钱字典
        var user_bet_sum_list={}  //用户下注数字典
        var user_bet_true_list=[]  //用户压对数组
        for (var i in betInfo_list) {
            var betInfo = betInfo_list[i]    //下注详情
            var res=parseInt(betInfo.bet_res);
            if(!user_win_list[betInfo["userId"]]){
                user_win_list[betInfo["userId"]]=0
            }
            if(!user_bet_sum_list[betInfo["userId"]]){
                user_bet_sum_list[betInfo["userId"]]=0
            }
            user_bet_sum_list[betInfo["userId"]] += parseInt(betInfo["bet_gold"]);
            if(win==res){
                if(user_bet_true_list.indexOf(betInfo["userId"])==-1){
                    user_bet_true_list.push(betInfo["userId"])
                }
                user_win_list[betInfo["userId"]]+= parseInt(parseInt(betInfo["bet_gold"]) * GAME_LONG_HU_DOU_ODDS[win]* parseFloat(100 - nGamblingWaterLevelGold)  / 100)
            }

            if(win==2 && res!=2 && !is_true_he){
                user_win_list[betInfo["userId"]]+= parseInt(betInfo["bet_gold"])
            }
        }
        log.info("user_win_list = "+ user_win_list);

        //开奖算法
        var dictAnalyseResults = {};
        dictAnalyseResults["win"] = win;
        dictAnalyseResults["win_user_list"] = user_win_list;  //# 用户获奖结果
        dictAnalyseResults["long_card"] = long_card;
        dictAnalyseResults["hu_card"] = hu_card;
        dictAnalyseResults["user_bet_sum_list"] = user_bet_sum_list;  //用户下注字典
        dictAnalyseResults["user_bet_true_list"] = user_bet_true_list;  //用户神算子数组

        return dictAnalyseResults

    }


    this.init();

}


function RandomNumForList(arr) {
    //从指定数组中选取随机值
    return arr[Math.floor((Math.random() * arr.length))]

}

function RandomNumBoth(Min, Max) {
    //生成指定范围内随机整数
    var Range = Max - Min;
    var Rand = Math.random();
    var num = Min + Math.round(Rand * Range); //四舍五入
    return num;
}

function getNumber(nCard) {
    //获取牌的牌数(扑克用)
   return parseInt(parseInt(nCard / 16)/ 16)
}



module.exports = arithmetic;